package com.lingx.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.lingx.bean.TokenBean;
@Component(value="lingxUserService")
public class UserService {

	private Cache<String,Boolean> cacheApiAuth ;
	private Cache<String,Boolean> cacheFuncAuth ;
	@Resource
	private JdbcTemplate jdbcTemplate;
	@Resource
	private LingxService lingxService;
	@PostConstruct
	public void init(){
		this.cacheFuncAuth=CacheBuilder.newBuilder().maximumSize(9999999).expireAfterAccess(30, TimeUnit.MINUTES).build();
		this.cacheApiAuth=CacheBuilder.newBuilder().maximumSize(9999999).expireAfterAccess(30, TimeUnit.MINUTES).build();
	}
	public void clearAuthCache() {
		this.cacheApiAuth.invalidateAll();
		this.cacheFuncAuth.invalidateAll();
	}
	
	public TokenBean getTokenBean(String account) {
		TokenBean bean=new TokenBean();
		bean.setAccount(account);
		Map<String,Object> user=this.jdbcTemplate.queryForMap("select id,name from tlingx_user where account=?", account);
		String userId=user.get("id").toString();
		bean.setUserId(userId);
		bean.setUserName(user.get("name").toString());
		StringBuilder orgids=new StringBuilder();
		StringBuilder roleids=new StringBuilder();
		List<Map<String,Object>> list=this.jdbcTemplate.queryForList("select role_id,org_id from tlingx_user_role where user_id=? order by type asc",userId);
		for(Map<String,Object> map:list) {
			if(orgids.indexOf(map.get("org_id").toString())==-1)
			orgids.append(map.get("org_id").toString()).append(",");
			
			if(roleids.indexOf(map.get("role_id").toString())==-1)
			roleids.append(map.get("role_id").toString()).append(",");
		}
		if(orgids.length()>0) {
			orgids.deleteCharAt(orgids.length()-1);
			roleids.deleteCharAt(roleids.length()-1);
		}
		bean.setOrgIds(orgids.toString());
		bean.setRoleIds(roleids.toString());
		bean.setLastLoginTime(System.currentTimeMillis());
		//System.out.println(JSON.toJSONString(bean));
		return bean;
	}
	

	public boolean isAuthApi(String userId,String apicode) {
		Boolean ret=null;
		
		if("true".equals(this.lingxService.getConfigValue("lingx.auth.api.cache", "true"))){//是否启用缓存，默认不启用
			StringBuilder sb=new StringBuilder();
			sb.append(userId).append("_").append(apicode);
			
			ret=this.cacheApiAuth.getIfPresent(sb.toString());
			if(ret==null){
				//System.out.println("不在缓存:"+sb);
				ret=this.getApiAuthByDb(userId, apicode);
				this.cacheApiAuth.put(sb.toString(), ret);
			}else{
				//System.out.println("在缓存:"+sb);
				return ret;
			}
		}else{
			ret=this.getApiAuthByDb(userId, apicode);
		}
		//ret=this.get(userId, module, func);
		return ret;
	}
	public boolean isAuthFunc(String userId,String module,String func) {
		Boolean ret=null;
		
		if("true".equals(this.lingxService.getConfigValue("lingx.auth.func.cache", "true"))){//是否启用缓存，默认不启用
			StringBuilder sb=new StringBuilder();
			sb.append(userId).append("_").append(module).append("_").append(func);
			
			ret=this.cacheFuncAuth.getIfPresent(sb.toString());
			if(ret==null){
				//System.out.println("不在缓存:"+sb);
				ret=this.getFuncAuthByDb(userId, module, func);
				this.cacheFuncAuth.put(sb.toString(), ret);
			}else{
				//System.out.println("在缓存:"+sb);
				return ret;
			}
		}else{
			ret=this.getFuncAuthByDb(userId, module, func);
		}
		//ret=this.get(userId, module, func);
		return ret;
	}
	
	private boolean getApiAuthByDb(String userId,String apicode) {
		boolean isAuth=false;
		String sql = "select count(*) from tlingx_user_role a,tlingx_role_api b  where  a.role_id=b.role_id and  a.user_id=? and b.apicode=? ";
		int c = this.lingxService.queryForInt(sql, userId,apicode );
		isAuth=c >= 1;
		return isAuth;
	}

	private boolean getFuncAuthByDb(String userId,String entityCode,String methodCode){
		boolean isAuth=false;
		if(this.jdbcTemplate.queryForObject("select count(*) from tlingx_func where module=? and func=?", Integer.class,entityCode,methodCode)==0)return false;
		int type=this.jdbcTemplate.queryForObject("select type from tlingx_func where module=? and func=? limit 1", Integer.class,entityCode,methodCode);
		if(type==1) {
			return true;
		}else if(type==3) {
			return false;
		}
		String sql = "select count(*) from tlingx_user_role a,tlingx_role_func b,tlingx_func c where  a.role_id=b.role_id and b.func_id=c.id and c.module=? and c.func=? and a.user_id=?";
		int c = this.lingxService.queryForInt(sql, entityCode, methodCode,userId );
		isAuth=c >= 1;
		return isAuth;
	}
	private boolean get_bak(String userId,String entityCode,String methodCode){
		String sql = "select type from tlingx_func where module=? and func=?";
		boolean isAuth=false;
		if(this.lingxService.queryForInt("select count(1) from tlingx_func where module=? and func=?", entityCode, methodCode)==0)return false;
		try {
			int c = this.lingxService.queryForInt(sql, entityCode, methodCode );
			switch (c) {
			case 1:// 公开
				isAuth = true;
				break;
			case 2:// 私有
				sql = "select count(*) from tlingx_user t,tlingx_user_role a,tlingx_role_func b,tlingx_func c where t.id=a.user_id and a.role_id=b.role_id and b.func_id=c.id and c.module=? and c.func=? and t.id=?";
				c = this.lingxService.queryForInt(sql, entityCode, methodCode,userId );
				sql = "select count(*) from tlingx_user_func t,tlingx_func a where t.user_id=? and t.func_id=a.id and a.module=? and a.func=? ";
				c=c+this.lingxService.queryForInt(sql, userId, entityCode, methodCode );
				isAuth=c >= 1;
				break;
			case 3:// 禁用
				isAuth = false;
				break;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return isAuth;
	}
	public void addUserOrg(Object userId, Object orgId) {
		try {
			if (isExistsUserOrg(userId, orgId))
				return;
			String sql = "insert into tlingx_user_org(id,org_id,user_id) values(uuid(),?,?)";
			this.jdbcTemplate.update(sql, orgId, userId);
			String fid = this.jdbcTemplate.queryForObject(
					"select fid from tlingx_org where id=?",String.class, orgId);
			if (!"0".equals(fid)) {
				addUserOrg(userId, fid);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void delUserOrg(Object userId, Object orgId) {
		if (!isExistsUserOrg(userId, orgId))
			return;
		List<Map<String, Object>> list = this.jdbcTemplate
				.queryForList(
						"select t.id from tlingx_org t where t.fid=? and exists (select 1 from tlingx_user_org where org_id=t.id and user_id=?)",
						orgId, userId);
		String fid = this.jdbcTemplate.queryForObject(
				"select fid from tlingx_org where id=?",String.class, orgId);
		this.jdbcTemplate.update(
				"delete from tlingx_user_org where org_id=? and user_id=?",
				orgId, userId);
		if (!"0".equals(fid)
				&& this.lingxService.queryForInt(
								"select count(*) from tlingx_user_org where user_id=? and org_id in ( select id from tlingx_org where fid=?)",
								userId, fid) == 0) {
			delUserOrg(userId, fid);
		}
		for (Map<String, Object> map : list) {
			delUserOrg(userId, map.get("id"));
		}
	}

	private boolean isExistsUserOrg(Object userId, Object orgId) {
		return this.lingxService.queryForInt(
						"select count(*) from tlingx_user_org where user_id=? and org_id=?",
						userId, orgId) != 0;
	}
	
	public String getHomePage(Object userId) {
		//可以通过用户来定制登陆后的默认页
		return this.lingxService.getConfigValue("lingx.main.home", "/main/home");
	}
	public List<String> getRoleCodeByUserId(Object userId){
		List<String> listRoleCode=new ArrayList<>();
		List<Map<String,Object>> list=this.jdbcTemplate.queryForList("select code from tlingx_role where id in (select role_id from tlingx_user_role where user_id=?)",userId);
		for(Map<String,Object> m:list) {
			listRoleCode.add(m.get("code").toString());
		}
		return listRoleCode;
	}
}
